﻿namespace AMS.Services.Impl;

public class SupplierService : ISupplierService
{
    private readonly DbContext _context;

    public SupplierService(DbContext context)
    {
        _context = context;
    }

    public async Task<ListResult<Supplier.QueryModel>> GetListAsync(CancellationToken cancellationToken)
    {
        var result = new ListResult<Supplier.QueryModel>();

        try
        {
            var suppliers = await _context.Set<Supplier>()
                .AsNoTracking()
                .ToListAsync(cancellationToken);

            result.Data = suppliers.Select(x => GetQueryModel(x));

            result.Status = OperationalResult.SUCCESS;
        }
        catch (Exception error)
        {
            result.Status = OperationalResult.ERROR;

            result.Message = error.ToString();
        }

        return result;
    }

    public async Task<PageResult<Supplier.QueryModel>> GetPageAsync(PageParameter input, CancellationToken cancellationToken)
    {
        var result = new PageResult<Supplier.QueryModel>();

        try
        {
            var suppliers = await _context.Set<Supplier>()
                .Skip((input.PageNum - 1) * input.PageSize)
                .Take(input.PageSize)
                .AsNoTracking()
                .ToListAsync(cancellationToken);

            result.Data = suppliers.Select(x => GetQueryModel(x));

            result.PageNum = input.PageNum;

            result.PageSize = input.PageSize;

            result.Total = _context.Set<Supplier>().Count();

            result.Status = OperationalResult.SUCCESS;
        }
        catch (Exception error)
        {
            result.Status = OperationalResult.ERROR;

            result.Message = error.ToString();
        }

        return result;
    }

    public async Task<OperationalResult> CreateAsync(Supplier.CreateModel supplier, CancellationToken cancellationToken)
    {
        var result = new OperationalResult();

        try
        {
            var entity = new Supplier
            {
                Name = supplier.Name,
                Contactor = supplier.Contactor,
                Phone = supplier.Phone,
            };

            await _context.Set<Supplier>().AddAsync(entity, cancellationToken);

            var affectedRows = await _context.SaveChangesAsync(cancellationToken);

            result.Status = affectedRows > 0 ? OperationalResult.SUCCESS : OperationalResult.FAILURE;

            result.Message = $"{affectedRows} rows affected.";
        }
        catch (Exception error)
        {
            result.Status = OperationalResult.ERROR;

            result.Message = error.ToString();
        }

        return result;
    }

    public async Task<OperationalResult> UpdateAsync(int id, Supplier.UpdateModel supplier, CancellationToken cancellationToken)
    {
        var result = new OperationalResult();

        try
        {
            var entity = await _context.Set<Supplier>()
                .Where(m => m.Id.Equals(id))
                .FirstOrDefaultAsync(cancellationToken);

            if (entity is null)
            {
                result.Status = OperationalResult.FAILURE;

                result.Message = "0 rows affected.";

                return result;
            }

            entity.Name = supplier.Name;
            entity.Contactor = supplier.Contactor;
            entity.Phone = supplier.Phone;

            _context.Set<Supplier>().Update(entity);

            var affectedRows = await _context.SaveChangesAsync(cancellationToken);

            result.Status = affectedRows > 0 ? OperationalResult.SUCCESS : OperationalResult.FAILURE;

            result.Message = $"{affectedRows} rows affected.";
        }
        catch (Exception error)
        {
            var exists = await _context.Set<Supplier>().AnyAsync(m => m.Id.Equals(id), cancellationToken);

            if (!exists)
            {
                result.Status = OperationalResult.FAILURE;

                result.Message = "0 rows affected.";
            }
            else
            {
                result.Status = OperationalResult.ERROR;

                result.Message = error.ToString();
            }
        }

        return result;
    }

    public async Task<OperationalResult> DeleteAsync(int id, CancellationToken cancellationToken)
    {
        var result = new OperationalResult();

        try
        {
            var supplier = await _context.Set<Supplier>()
                .Where(m => m.Id.Equals(id))
                .FirstOrDefaultAsync(cancellationToken);

            if (supplier is null)
            {
                result.Status = OperationalResult.FAILURE;

                result.Message = "0 rows affected.";

                return result;
            }

            _context.Set<Supplier>().Remove(supplier);

            var affectedRows = await _context.SaveChangesAsync(cancellationToken);

            result.Status = affectedRows > 0 ? OperationalResult.SUCCESS : OperationalResult.FAILURE;

            result.Message = $"{affectedRows} rows affected.";
        }
        catch (Exception error)
        {
            result.Status = OperationalResult.ERROR;

            result.Message = error.ToString();
        }

        return result;
    }

    public static Supplier.QueryModel GetQueryModel(Supplier supplier)
    {
        return new Supplier.QueryModel
        {
            Id = supplier.Id,
            CreatedDate = supplier.CreatedDate,
            LastModifiedDate = supplier.LastModifiedDate,
            Name = supplier.Name,
            Contactor = supplier.Contactor,
            Phone = supplier.Phone,
        };
    }
}